#pragma once
#include "LogMessage.hpp"
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "C++_pool_thread.hpp"
#include <functional>
#include "task.hpp"
#include "protocol.hpp"

using namespace std;
#define DEFAULT_IP "0.0.0.0"


class tcp_server
{
public:
    tcp_server(uint16_t port)
        : _ip(DEFAULT_IP), _port(port), _monitor_skfd(-1)
    {}

    void server_init()
    {
        // create socket
        _monitor_skfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_monitor_skfd < 0){logMessage(ERROR, "create monitor socket error"); exit(0);}
        else
            logMessage(NORMAL, "create monitor socket success");

        // bind port
        struct sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_port = htons(_port);
        server.sin_addr.s_addr = inet_addr(_ip.c_str());
        socklen_t len = sizeof(server);

        int check = bind(_monitor_skfd, (struct sockaddr *)&server, len);
        if (check == -1){logMessage(ERROR, "bind socket error"); exit(0);}
        else
            logMessage(NORMAL, "bind socket success");

        // 设置监听套接字
        check = listen(_monitor_skfd, 5);
        if (check == -1){logMessage(ERROR, "set listen socket error"); exit(0);}
        else
            logMessage(NORMAL, "set listen socket success");
    }

    void server_start(const fun& _main_call)
    {
        thread_pool<task> deal_process;
        deal_process.run();

        while (true)
        {
            struct sockaddr_in client;
            socklen_t len;
            int fd = accept(_monitor_skfd, (struct sockaddr *)&client, &len);
            if (fd < 0) {logMessage(ERROR, "accept client sockfd error"); continue;}
            else logMessage(NORMAL, "accept client sockfd success");
            
            deal_process.push(task(fd, _main_call, hand_deal));
        }
    }

private:
    string _ip;
    uint16_t _port;
    int _monitor_skfd;
};
